#pragma once
#ifndef __HWINHANDLE_H__
#define __HWINHANDLE_H__

#include "hwindef.h"
#include "hwinmessage.h"
#include "hwinobject.h"
#include "hwinlog.h"

namespace harlinn
{
    namespace windows
    {
        class Control;
        class ModuleHandle;
        class BitmapHandle;
        class IconHandle;
        class CursorHandle;
        class Menu;
        class Accelerator;
        class DeviceContextHandle;
        class BrushHandle;
        class PenHandle;
        class FontHandle;



        


        class Handle : public Object
        {
            friend class ModuleHandle;
            friend class BitmapHandle;
            friend class IconHandle;
            friend class CursorHandle;
            friend class Menu;
            friend class Accelerator;

            LPVOID value;
            bool ownsHandle;
        protected:
            Handle()
                : value(0), 
                ownsHandle(false)
            {
                HWIN_TRACE();
            }
        private:

            Handle(const Handle& theHandle)
                : value(theHandle.value), 
                ownsHandle(theHandle.ownsHandle)
            {
                HWIN_TRACE();
            }

            Handle(Handle&& theHandle)
                : value(theHandle.value), 
                ownsHandle(theHandle.ownsHandle)
            {
                HWIN_TRACE();
                theHandle.ownsHandle = false;
            }

            Handle& operator = (const Handle& theHandle)
            {
                HWIN_TRACE();
                return *this;
            }

            Handle& operator = (Handle&& theHandle)
            {
                HWIN_TRACE();
                return *this;
            }

        protected:
            
            Handle& SetValue(LPVOID theHandle, bool closeHandle = true) 
            { 
                HWIN_TRACE();
                value = theHandle;ownsHandle = closeHandle; return *this; 
            }
        public:
            typedef Object Base;
        protected:
            explicit Handle(LPVOID theHandle, bool closeHandle = true)
                : value(theHandle), 
                ownsHandle(closeHandle)
            {
                HWIN_TRACE();
            }

        public:
            virtual ~Handle()
            {
                HWIN_TRACE();
            }

            operator LPVOID() const
            {
                return value;
            }

            LPVOID Value() const 
            { 
                return value; 
            }

            bool OwnsHandle() const
            {
                return ownsHandle;
            }
        };


        class SystemHandle : public Handle
        {
        public:
            typedef Handle Base;
        protected:
            explicit SystemHandle(LPVOID theHandle, bool closeHandle = true)
                : Base(theHandle, closeHandle)
            {
                HWIN_TRACE();
            }
        protected:
            SystemHandle()
            {
                HWIN_TRACE();
            }
            
        public:
            bool IsValid()
            {
                return Value() != INVALID_HANDLE_VALUE;
            }
            HWIN_EXPORT virtual ~SystemHandle();


            operator HANDLE() const
            {
                HWIN_TRACE();
                return static_cast<HANDLE>(Value());
            }

            HANDLE GetHANDLE() const
            {
                HWIN_TRACE();
                return static_cast<HANDLE>(Value());
            }

        };


        class ModuleHandle : public Handle
        {
        public:
            typedef Handle Base;

            HWIN_EXPORT explicit ModuleHandle(HMODULE hModule, bool closeHandle = true);

            HWIN_EXPORT ModuleHandle(const wchar_t* theModuleName, DWORD flags = 0);
            HWIN_EXPORT ModuleHandle(const String& theModuleName, DWORD flags = 0);
            HWIN_EXPORT ModuleHandle(std::shared_ptr<String> theModuleName, DWORD flags = 0);

            HWIN_EXPORT virtual ~ModuleHandle();


            HWIN_EXPORT String GetModuleFileName() const;

            operator HMODULE() const
            {
                HWIN_TRACE();
                return static_cast<HMODULE>(Value());
            }

            HMODULE GetHMODULE() const
            {
                HWIN_TRACE();
                return static_cast<HMODULE>(Value());
            }


            HWIN_EXPORT static std::shared_ptr<ModuleHandle> Current();


        };


        class GraphicsDeviceObjectHandle : public Handle
        {
        public:
            typedef Handle Base;

        protected:
            HWIN_EXPORT GraphicsDeviceObjectHandle(HGDIOBJ theHandle, bool closeHandle = true);
            GraphicsDeviceObjectHandle() 
            {
                HWIN_TRACE();
            }

        };

        class BitmapHandle : public GraphicsDeviceObjectHandle
        {
            friend class DeviceContextHandle;
            typedef std::map<HBITMAP,BitmapHandle*> map_t;
            static map_t map;
            HWIN_EXPORT static void AddHandleToMap(HBITMAP hElement,BitmapHandle* theHandle);
            HWIN_EXPORT static BitmapHandle* GetHandleFromMap(HBITMAP hElement);
            HWIN_EXPORT static void RemoveHandleFromMap(HBITMAP hElement);
        public:
            typedef GraphicsDeviceObjectHandle Base;

            HWIN_EXPORT BitmapHandle(HBITMAP theHandle, bool ownsHandle = true);

            HWIN_EXPORT BitmapHandle(int resourceId, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);

            HWIN_EXPORT BitmapHandle(const wchar_t* theBitmapName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT BitmapHandle(const String& theBitmapName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT BitmapHandle(std::shared_ptr<String> theBitmapName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);

            HWIN_EXPORT BitmapHandle(std::shared_ptr<ModuleHandle> theModule, int resourceId, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT BitmapHandle(std::shared_ptr<ModuleHandle> theModule, const wchar_t* theBitmapName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT BitmapHandle(std::shared_ptr<ModuleHandle> theModule, const String& theBitmapName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT BitmapHandle(std::shared_ptr<ModuleHandle> theModule, std::shared_ptr<String> theBitmapName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);

            HWIN_EXPORT ~BitmapHandle();


            HWIN_EXPORT static std::shared_ptr<BitmapHandle> FromHandle(HBITMAP theHandle, bool ownsHandle = true);

            operator HBITMAP() const
            {
                HWIN_TRACE();
                return static_cast<HBITMAP>(Value());
            }

            HBITMAP GetHBITMAP() const
            {
                HWIN_TRACE();
                return static_cast<HBITMAP>(Value());
            }

            HWIN_EXPORT SIZE Size() const;

            HWIN_EXPORT static std::shared_ptr<BitmapHandle> LoadFromFile(const String& theFileMame);



        };

        class ImageListHandle;
        class IconHandle : public Handle
        {
        public:
            typedef Handle Base;

            HWIN_EXPORT static std::shared_ptr<IconHandle> Question;
            HWIN_EXPORT static std::shared_ptr<IconHandle> WinLogo;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Warning;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Error;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Information;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Shield;

            HWIN_EXPORT static std::shared_ptr<IconHandle> Question16x16;
            HWIN_EXPORT static std::shared_ptr<IconHandle> WinLogo16x16;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Warning16x16;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Error16x16;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Information16x16;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Shield16x16;

            HWIN_EXPORT static std::shared_ptr<IconHandle> Question24x24;
            HWIN_EXPORT static std::shared_ptr<IconHandle> WinLogo24x24;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Warning24x24;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Error24x24;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Information24x24;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Shield24x24;

            HWIN_EXPORT static std::shared_ptr<IconHandle> Question32x32;
            HWIN_EXPORT static std::shared_ptr<IconHandle> WinLogo32x32;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Warning32x32;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Error32x32;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Information32x32;
            HWIN_EXPORT static std::shared_ptr<IconHandle> Shield32x32;

            HWIN_EXPORT explicit IconHandle(HICON hIcon, bool closeHandle = true);

            HWIN_EXPORT IconHandle(int resourceId, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);

            HWIN_EXPORT IconHandle(const wchar_t* theIconName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT IconHandle(const String& theIconName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT IconHandle(std::shared_ptr<String> theIconName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);

            HWIN_EXPORT IconHandle(std::shared_ptr<ModuleHandle> theModule, int resourceId, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT IconHandle(std::shared_ptr<ModuleHandle> theModule, const wchar_t* theIconName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT IconHandle(std::shared_ptr<ModuleHandle> theModule, const String& theIconName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT IconHandle(std::shared_ptr<ModuleHandle> theModule, std::shared_ptr<String> theIconName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);

            HWIN_EXPORT ~IconHandle();

            operator HICON() const
            {
                HWIN_TRACE();
                return static_cast<HICON>(Value());
            }

            HICON GetHICON() const
            {
                HWIN_TRACE();
                return static_cast<HICON>(Value());
            }


        };


        class CursorHandle : public Handle
        {
        public:
            typedef Handle Base;

            HWIN_EXPORT static std::shared_ptr<CursorHandle> Normal;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> IBeam;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> Wait;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> Cross;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> Up;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> Size;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> SizeNWSE;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> SizeNESW;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> SizeWE;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> SizeNS;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> No;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> Hand;
            HWIN_EXPORT static std::shared_ptr<CursorHandle> AppStarting;


            HWIN_EXPORT CursorHandle(int resourceId, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);

            HWIN_EXPORT CursorHandle(const wchar_t* theCursorName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT CursorHandle(const String& theCursorName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT CursorHandle(std::shared_ptr<String> theCursorName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);

            HWIN_EXPORT CursorHandle(std::shared_ptr<ModuleHandle> theModule, int resourceId, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT CursorHandle(std::shared_ptr<ModuleHandle> theModule, const wchar_t* theCursorName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT CursorHandle(std::shared_ptr<ModuleHandle> theModule, const String& theCursorName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);
            HWIN_EXPORT CursorHandle(std::shared_ptr<ModuleHandle> theModule, std::shared_ptr<String> theCursorName, int width = 0, int height = 0,DWORD flags = LR_SHARED|LR_DEFAULTSIZE);

            HWIN_EXPORT ~CursorHandle();
            

            operator HCURSOR() const
            {
                HWIN_TRACE();
                return static_cast<HCURSOR>(Value());
            }

            HCURSOR GetHCURSOR() const
            {
                HWIN_TRACE();
                return static_cast<HCURSOR>(Value());
            }


        };


        class MenuHandle : public Handle
        {
        public:
            typedef Handle Base;

            HWIN_EXPORT MenuHandle(HMENU hMenu, bool ownsHandle = true);

            HWIN_EXPORT ~MenuHandle( );

            HWIN_EXPORT MenuHandle& AddStyle(DWORD style);

            HWIN_EXPORT MenuHandle& AppendMenu(UINT uFlags,UINT_PTR uIDNewItem,const wchar_t* newItem);
            HWIN_EXPORT MenuHandle& CheckMenuRadioItem(UINT idFirst,UINT idLast,UINT idCheck,UINT uFlags);
            HWIN_EXPORT MenuHandle& DeleteMenu(UINT position,UINT uFlags);
            HWIN_EXPORT MenuHandle& EnableMenuItem(UINT idOfItem, UINT enableFlags);
            HWIN_EXPORT static void EndMenu( );

            HWIN_EXPORT static long GetCheckMarkDimensions();

            HWIN_EXPORT UINT GetMenuDefaultItem(bool byPosition, UINT flags);

            HWIN_EXPORT const MenuHandle& GetMenuInfo(LPMENUINFO lpcmi) const;
            HWIN_EXPORT const MenuHandle& GetMenuInfo(MENUINFO& lpcmi) const;
            HWIN_EXPORT std::shared_ptr<MENUINFO> GetMenuInfo( ) const;

            HWIN_EXPORT int GetMenuItemCount( ) const;
            HWIN_EXPORT UINT GetMenuItemID(int menuItemPosition) const;

            HWIN_EXPORT const MenuHandle& GetMenuItemInfo(UINT itemIdOrPosition, bool byPosition,LPMENUITEMINFO lpmii) const;
            HWIN_EXPORT const MenuHandle& GetMenuItemInfo(UINT itemIdOrPosition, bool byPosition,MENUITEMINFO& lpmii) const;
            HWIN_EXPORT std::shared_ptr<MENUITEMINFO> GetMenuItemInfo(UINT itemIdOrPosition, bool byPosition) const;

            HWIN_EXPORT UINT GetMenuState(UINT itemIdOrPosition,bool byPosition) const;

            HWIN_EXPORT int GetMenuStringLength(UINT itemIdOrPosition,bool byPosition) const;
            HWIN_EXPORT int GetMenuString(UINT itemIdOrPosition,LPTSTR lpString,int nMaxCount,bool byPosition) const;
            HWIN_EXPORT std::shared_ptr<String> GetMenuString(UINT itemIdOrPosition,bool byPosition) const;

            HWIN_EXPORT HMENU GetSubMenu(int position) const;

            HWIN_EXPORT MenuHandle& InsertMenu(UINT uPosition,UINT uFlags, UINT_PTR itemIdOrPosition,LPCTSTR lpNewItem);
            HWIN_EXPORT MenuHandle& InsertMenuItem(UINT itemIdOrPosition,bool byPosition,LPCMENUITEMINFO lpmii);
            HWIN_EXPORT MenuHandle& InsertMenuItem(UINT itemIdOrPosition,bool byPosition,const MENUITEMINFO& lpmii);

            HWIN_EXPORT bool IsMenu() const;


            HWIN_EXPORT static std::shared_ptr<MenuHandle> LoadMenu(LPCTSTR lpMenuName);
            HWIN_EXPORT static std::shared_ptr<MenuHandle> LoadMenu(std::shared_ptr<ModuleHandle> module,LPCTSTR lpMenuName);
            HWIN_EXPORT static std::shared_ptr<MenuHandle> LoadMenu(HINSTANCE module,LPCTSTR lpMenuName);

            HWIN_EXPORT MenuHandle& ModifyMenu(UINT uPosition,UINT uFlags,UINT_PTR uIDNewItem,LPCTSTR lpNewItem);

            HWIN_EXPORT MenuHandle& RemoveMenu(UINT uPosition,UINT uFlags);

            HWIN_EXPORT MenuHandle& SetMenuDefaultItem(UINT itemIdOrPosition,bool byPosition);

            HWIN_EXPORT MenuHandle& SetMenuItemBitmaps(UINT itemIdOrPosition,bool byPosition,HBITMAP hBitmapUnchecked,HBITMAP hBitmapChecked);

            HWIN_EXPORT MenuHandle& SetMenuItemInfo(UINT uItem, BOOL fByPosition, LPMENUITEMINFO lpmii);
            HWIN_EXPORT MenuHandle& SetMenuInfo(LPCMENUINFO lpcmi);
            HWIN_EXPORT MenuHandle& SetMenuInfo(const MENUINFO& lpcmi);

            operator HMENU() const
            {
                HWIN_TRACE();
                return static_cast<HMENU>(Value());
            }

            HMENU GetHMENU() const
            {
                HWIN_TRACE();
                return static_cast<HMENU>(Value());
            }
        };


        enum class SysColor : int
        {
            ScrollBar         = 0,
            Desktop        = 1,
            ActiveCaption     = 2,
            InactiveCaption   = 3,
            Menu              = 4,
            Window            = 5,
            WindowFrame       = 6,
            MenuText          = 7,
            WindowText        = 8,
            ActiveCaptionText = 9,
            ActiveBorder      = 10,
            InactiveBorder    = 11,
            AppWorkspace      = 12,
            Highlight         = 13,
            HighlightText     = 14,
            ButtonFace        = 15,
            Control           = 15,
            ButtonShadow      = 16,
            ControlDark       = 16,
            GrayText          = 17,
            ControlText       = 18,
            InactiveCaptionText = 19,
            ControlLight      = 20,
            ButtonHighlight   = 20,
            ControlDarkDark   = 21,
            ControlLightLight = 22,
            InfoText          = 23,
            Info              = 24,
            HotTrack          = 26,
            GradientActiveCaption = 27,
            GradientInactiveCaption = 28,
            MenuHighlight       = 29,
            MenuBar           = 30
        };


        class ColorRef 
        {
            COLORREF color;
        public:
            inline ColorRef() : color(0) 
            {
                HWIN_TRACE();
            }
            inline ColorRef(BYTE r, BYTE g, BYTE b) : color(RGB(r,g,b)) 
            {
                HWIN_TRACE();
            }
            inline ColorRef(SysColor sysColor) : color( GetSysColor(int(sysColor)) ) 
            {
                HWIN_TRACE();
            }

            inline ColorRef(COLORREF colorref) : color( colorref ) 
            {
                HWIN_TRACE();
            }
            inline ColorRef(const ColorRef& colorref) : color( colorref ) 
            {
                HWIN_TRACE();
            }

            inline ColorRef& operator = (COLORREF colorref) 
            { 
                HWIN_TRACE();
                color =  colorref;
                return *this;
            }

            inline ColorRef& operator = (const ColorRef& colorref) 
            { 
                HWIN_TRACE();
                color =  colorref.color;
                return *this;
            }

            inline bool operator == (COLORREF colorref) const
            { 
                HWIN_TRACE();
                return color == colorref;
            }

            inline bool operator != (COLORREF colorref) const
            { 
                HWIN_TRACE();
                return color != colorref;
            }

            inline bool operator <= (COLORREF colorref) const
            { 
                HWIN_TRACE();
                return color <= colorref;
            }

            inline bool operator < (COLORREF colorref) const
            { 
                HWIN_TRACE();
                return color < colorref;
            }

            inline bool operator >= (COLORREF colorref) const
            { 
                HWIN_TRACE();
                return color >= colorref;
            }

            inline bool operator > (COLORREF colorref) const
            { 
                HWIN_TRACE();
                return color > colorref;
            }

            inline BYTE Red() const 
            { 
                HWIN_TRACE();
                return GetRValue(color); 
            }
            inline BYTE Green() const 
            { 
                HWIN_TRACE();
                return GetGValue(color); 
            }
            inline BYTE Blue() const 
            { 
                HWIN_TRACE();
                return GetBValue(color); 
            }

            inline operator COLORREF() const 
            { 
                HWIN_TRACE();
                return color; 
            }

            inline bool Invalid() const
            {
                HWIN_TRACE();
                return color == CLR_INVALID;
            }

        };

        enum class BrushStyle : UINT
        {
            Solid            = 0,
            Null             = 1,
            Hollow           = Null,
            Hatched          = 2,
            Pattern          = 3,
            Indexed          = 4,
            DibPattern       = 5,
            DibPatternPT     = 6,
            Pattern8X8       = 7,
            DibPattern8X8    = 8,
            MonoPattern      = 9
        };

        enum class HatchStyle : UINT
        {
            Horizontal       = 0,       /* ----- */
            Vertical         = 1,       /* ||||| */
            ForwardDiagonal  = 2,       /* \\\\\ */
            BackwardDiagonal = 3,       /* ///// */
            Cross            = 4,       /* +++++ */
            DiagonalCross    = 5        /* xxxxx */
        };

        enum class PenStyle : UINT
        {
            Solid            = 0,
            Dash             = 1,       /* -------  */
            Dot              = 2,       /* .......  */
            DashDot          = 3,       /* _._._._  */
            DashDotDot       = 4,       /* _.._.._  */
            Null             = 5,
            InsideFrame      = 6,
            UserStyle        = 7,
            Alternate        = 8
        };

        enum class PenEndCaps : UINT
        {
            Round     = 0x00000000,
            Square    = 0x00000100,
            Flat      = 0x00000200
        };

        enum class PenJoin : UINT
        {
            Round       = 0x00000000,
            Bevel       = 0x00001000,
            Miter       = 0x00002000
        };

        enum class PenType : UINT
        {
            Cosmetic         = 0x00000000,
            Geometric        = 0x00010000
        };



        class BrushHandle : public GraphicsDeviceObjectHandle
        {
            friend class DeviceContextHandle;
            typedef std::map<HBRUSH,BrushHandle*> map_t;
            static map_t map;
            HWIN_EXPORT static void AddHandleToMap(HBRUSH hElement,BrushHandle* theHandle);
            HWIN_EXPORT static BrushHandle* GetHandleFromMap(HBRUSH hElement);
            HWIN_EXPORT static void RemoveHandleFromMap(HBRUSH hElement);
        public:
            typedef GraphicsDeviceObjectHandle Base;
            HWIN_EXPORT BrushHandle(HBRUSH theHandle, bool ownsHandle = true);

            HWIN_EXPORT BrushHandle(const LOGBRUSH& theLogBrush);
            HWIN_EXPORT BrushHandle(std::shared_ptr<const LOGBRUSH> theLogBrush);
            HWIN_EXPORT explicit BrushHandle(COLORREF color);
            HWIN_EXPORT explicit BrushHandle(SysColor sysColor);


            HWIN_EXPORT ~BrushHandle( );

            operator HBRUSH() const
            {
                HWIN_TRACE();
                return static_cast<HBRUSH>(Value());
            }

            HBRUSH GetHBRUSH() const
            {
                HWIN_TRACE();
                return static_cast<HBRUSH>(Value());
            }
        };


        class PenHandle : public GraphicsDeviceObjectHandle
        {
            friend class DeviceContextHandle;
            typedef std::map<HPEN,PenHandle*> map_t;
            static map_t map;
            HWIN_EXPORT static void AddHandleToMap(HPEN hElement,PenHandle* theHandle);
            HWIN_EXPORT static PenHandle* GetHandleFromMap(HPEN hElement);
            HWIN_EXPORT static void RemoveHandleFromMap(HPEN hElement);
        public:
            typedef GraphicsDeviceObjectHandle Base;
            HWIN_EXPORT PenHandle(HPEN theHandle, bool ownsHandle = true);

            HWIN_EXPORT ~PenHandle( );

            operator HPEN() const
            {
                HWIN_TRACE();
                return static_cast<HPEN>(Value());
            }

            HPEN GetHPEN() const
            {
                HWIN_TRACE();
                return static_cast<HPEN>(Value());
            }
        };

        class FontHandle : public GraphicsDeviceObjectHandle
        {
            friend class DeviceContextHandle;
            typedef std::map<HFONT,FontHandle*> map_t;
            static map_t map;
            HWIN_EXPORT static void AddHandleToMap(HFONT hElement,FontHandle* theHandle);
            HWIN_EXPORT static FontHandle* GetHandleFromMap(HFONT hElement);
            HWIN_EXPORT static void RemoveHandleFromMap(HFONT hElement);
        public:
            typedef GraphicsDeviceObjectHandle Base;
            HWIN_EXPORT FontHandle(HFONT theHandle, bool ownsHandle = true);

            HWIN_EXPORT ~FontHandle( );

            operator HFONT() const
            {
                HWIN_TRACE();
                return static_cast<HFONT>(Value());
            }

            HFONT GetHFONT() const
            {
                HWIN_TRACE();
                return static_cast<HFONT>(Value());
            }
        };

        enum class RegionType : int
        {
            Error         = 0,
            Null          = 1,
            Simple        = 2,
            Complex       = 3
        };


        class RegionHandle : public GraphicsDeviceObjectHandle
        {
            friend class DeviceContextHandle;
            typedef std::map<HRGN,RegionHandle*> map_t;
            static map_t map;
            HWIN_EXPORT static void AddHandleToMap(HRGN hElement,RegionHandle* theHandle);
            HWIN_EXPORT static RegionHandle* GetHandleFromMap(HRGN hElement);
            HWIN_EXPORT static void RemoveHandleFromMap(HRGN hElement);
        public:
            typedef GraphicsDeviceObjectHandle Base;
            HWIN_EXPORT RegionHandle(HRGN theHandle, bool ownsHandle = true);

            HWIN_EXPORT ~RegionHandle( );

            operator HRGN() const
            {
                HWIN_TRACE();
                return static_cast<HRGN>(Value());
            }

            HRGN GetHRGN() const
            {
                HWIN_TRACE();
                return static_cast<HRGN>(Value());
            }
        };

        class PaletteHandle : public GraphicsDeviceObjectHandle
        {
            friend class DeviceContextHandle;
            typedef std::map<HPALETTE,PaletteHandle*> map_t;
            static map_t map;
            HWIN_EXPORT static void AddHandleToMap(HPALETTE hElement,PaletteHandle* theHandle);
            HWIN_EXPORT static PaletteHandle* GetHandleFromMap(HPALETTE hElement);
            HWIN_EXPORT static void RemoveHandleFromMap(HPALETTE hElement);
        public:
            typedef GraphicsDeviceObjectHandle Base;
            HWIN_EXPORT PaletteHandle(HPALETTE theHandle, bool ownsHandle = true);

            HWIN_EXPORT ~PaletteHandle( );

            operator HPALETTE() const
            {
                HWIN_TRACE();
                return static_cast<HPALETTE>(Value());
            }

            HPALETTE GetHPALETTE() const
            {
                HWIN_TRACE();
                return static_cast<HPALETTE>(Value());
            }
        };

#pragma pack(push,8)
        class Size;
        class Point
        {
            int x;
            int y;
        public:
            Point()
                : x(0),y(0)
            {
                HWIN_TRACE();
            }

            Point(int theXValue,int theYValue)
                : x(theXValue),y(theYValue)
            {
                HWIN_TRACE();
            }

            explicit Point(int theXYValue)
                : x(theXYValue),y(theXYValue)
            {
                HWIN_TRACE();
            }

            Point(const POINT& pt)
                : x(pt.x),y(pt.y)
            {
                HWIN_TRACE();
            }

            Point(const SIZE& size)
                : x(size.cx),y(size.cy)
            {
                HWIN_TRACE();
            }

            Point(const Point& pt)
                : x(pt.x),y(pt.y)
            {
                HWIN_TRACE();
            }


            Point(const Size& size);

            Point& operator = (const POINT& pt)
            {
                HWIN_TRACE();
                x = pt.x;
                y = pt.y;
                return *this;
            }

            Point& operator = (const SIZE& size)
            {
                HWIN_TRACE();
                x = size.cx;
                y = size.cy;
                return *this;
            }

            Point& operator = (const Size& size);


            Point& operator = (const Point& pt)
            {
                HWIN_TRACE();
                x = pt.x;
                y = pt.y;
                return *this;
            }


            int X() const 
            {
                HWIN_TRACE();
                return x;
            }
            Point& SetX(int theValue) 
            {
                HWIN_TRACE();
                x=theValue;
                return *this;
            }
            int Y() const 
            {
                HWIN_TRACE();
                return y;
            }
            Point& SetY(int theValue) 
            {
                HWIN_TRACE();
                y=theValue;
                return *this;
            }
            Point& Set(int theXValue,int theYValue) 
            {
                HWIN_TRACE();
                x=theXValue;
                y=theYValue;
                return *this;
            }

            operator POINT& () 
            { 
                HWIN_TRACE();
                return *((POINT*)&x); 
            }
            operator const POINT& () const 
            { 
                HWIN_TRACE();
                return *((POINT*)&x); 
            }


        };

        class Size
        {
            int width;
            int height;
        public:
            Size()
                : width(0),height(0)
            {
                HWIN_TRACE();
            }


            Size(int theWidth,int theHeight)
                : width(theWidth),height(theHeight)
            {
                HWIN_TRACE();
            }

            explicit Size(int theValue)
                : width(theValue),height(theValue)
            {
                HWIN_TRACE();
            }

            Size(const POINT& pt)
                : width(pt.x),height(pt.y)
            {
                HWIN_TRACE();
            }

            Size(const SIZE& size)
                : width(size.cx),height(size.cy)
            {
                HWIN_TRACE();
            }

            Size(const Point& pt)
                : width(pt.X()),height(pt.Y())
            {
                HWIN_TRACE();
            }


            Size(const Size& size)
                : width(size.width),height(size.height)
            {
                HWIN_TRACE();
            }

            Size& operator = (const SIZE& size)
            {
                HWIN_TRACE();
                width = size.cx;
                height = size.cy;
                return *this;
            }

            Size& operator = (const POINT& pt)
            {
                HWIN_TRACE();
                width = pt.x;
                height = pt.y;
                return *this;
            }

            Size& operator = (const Size& size)
            {
                HWIN_TRACE();
                width = size.width;
                height = size.height;
                return *this;
            }

            Size& operator = (const Point& pt)
            {
                HWIN_TRACE();
                width = pt.X();
                height = pt.Y();
                return *this;
            }

            int Width() const 
            {
                HWIN_TRACE();
                return width;
            }
            Size& SetWidth(int theWidth) 
            {
                HWIN_TRACE();
                width=theWidth;
                return *this;
            }
            int Height() const 
            {
                HWIN_TRACE();
                return height;
            }
            Size& SetHeight(int theValue) 
            {
                HWIN_TRACE();
                height=theValue;
                return *this;
            }
            Size& Set(int theWidth,int theHeight) 
            {
                HWIN_TRACE();
                width=theWidth;
                height=theHeight;
                return *this;
            }

            operator SIZE& () 
            { 
                HWIN_TRACE();
                return *((SIZE*)&width); 
            }
            operator const SIZE& () const 
            { 
                HWIN_TRACE();
                return *((SIZE*)&width); 
            }

        };

        inline Point::Point(const Size& size)
            : x(size.Width()),y(size.Height())
        {
            HWIN_TRACE();
        }

        inline Point& Point::operator = (const Size& size)
        {
            HWIN_TRACE();
            x = size.Width();
            y = size.Height();
            return *this;
        }


        class Rectangle
        {
            int left;
            int top;
            int right;
            int bottom;
        public:
            Rectangle()
                : left(0),top(0),right(0),bottom(0)
            {
                HWIN_TRACE();
            }

            Rectangle(const Rectangle& other)
                : left(other.left),top(other.top),right(other.right),bottom(other.bottom)
            {
                HWIN_TRACE();
            }

            Rectangle(const RECT& other)
                : left(other.left),top(other.top),right(other.right),bottom(other.bottom)
            {
                HWIN_TRACE();
            }

            Rectangle(const Point& position, const Size& size)
                : left(position.X()),top(position.Y()),right(position.X()+size.Width()),bottom(position.Y()+size.Height())
            {
                HWIN_TRACE();
            }

            Rectangle(const Size& size)
                : left(0),top(0),right(size.Width()),bottom(size.Height())
            {
                HWIN_TRACE();
            }


            explicit Rectangle(int size)
                : left(0),top(0),right(size),bottom(size)
            {
                HWIN_TRACE();
            }

            Rectangle& operator = (const Rectangle& other)
            {
                left = other.left;
                top = other.top;
                right = other.right;
                bottom = other.bottom;
                return *this;
            }

            Rectangle& operator = (const RECT& other)
            {
                left = other.left;
                top = other.top;
                right = other.right;
                bottom = other.bottom;
                return *this;
            }


            int X() const 
            {
                HWIN_TRACE();
                return left;
            }
            Rectangle& SetX(int theValue) 
            {
                HWIN_TRACE();
                left=theValue;
                return *this;
            }
            int Y() const 
            {
                HWIN_TRACE();
                return top;
            }
            Rectangle& SetY(int theValue) 
            {
                HWIN_TRACE();
                top=theValue;
                return *this;
            }

            int Width() const 
            {
                HWIN_TRACE();
                return labs(right-left);
            }
            Rectangle& SetWidth(int theWidth) 
            {
                HWIN_TRACE();
                right=left + theWidth;
                return *this;
            }
            int Height() const 
            {
                HWIN_TRACE();
                return labs(bottom - top);
            }
            Rectangle& SetHeight(int theValue) 
            {
                HWIN_TRACE();
                bottom=top+theValue;
                return *this;
            }


            int Left() const 
            {
                HWIN_TRACE();
                return left;
            }
            Rectangle& SetLeft(int theValue) 
            {
                HWIN_TRACE();
                left=theValue;
                return *this;
            }
            int Top() const 
            {
                HWIN_TRACE();
                return top;
            }
            Rectangle& SetTop(int theValue) 
            {
                HWIN_TRACE();
                top=theValue;
                return *this;
            }

            int Right() const 
            {
                HWIN_TRACE();
                return right;
            }
            Rectangle& SetRight(int theValue) 
            {
                HWIN_TRACE();
                right=theValue;
                return *this;
            }
            int Bottom() const 
            {
                HWIN_TRACE();
                return bottom;
            }
            Rectangle& SetBottom(int theValue) 
            {
                HWIN_TRACE();
                bottom=theValue;
                return *this;
            }

            Point Position() const
            {
                HWIN_TRACE();
                return Point(left,top);
            }

            Rectangle& SetPosition(const Point& pt)
            {
                HWIN_TRACE();
                int width = right-left;
                int height = bottom - top;
                left = pt.X();
                top = pt.Y();
                right = left + width;
                bottom = top + height;
                return *this;
            }

            Point LeftTop() const
            {
                HWIN_TRACE();
                return Point(left,top);
            }

            Rectangle& SetLeftTop(const Point& pt)
            {
                HWIN_TRACE();
                left = pt.X();
                top = pt.Y();
                return *this;
            }

            Rectangle& SetLeftTop(int theLeft, int theTop)
            {
                HWIN_TRACE();
                left = theLeft;
                top = theTop;
                return *this;
            }

            Point RightTop() const
            {
                HWIN_TRACE();
                return Point(right,top);
            }


            Rectangle& SetRightTop(const Point& pt)
            {
                HWIN_TRACE();
                right = pt.X();
                top = pt.Y();
                return *this;
            }

            Rectangle& SetRightTop(int theRight, int theTop)
            {
                HWIN_TRACE();
                right = theRight;
                top = theTop;
                return *this;
            }

            Point LeftBottom() const
            {
                HWIN_TRACE();
                return Point(left,bottom);
            }

            Rectangle& SetLeftBottom(const Point& pt)
            {
                HWIN_TRACE();
                left = pt.X();
                bottom = pt.Y();
                return *this;
            }

            Rectangle& SetLeftBottom(int theLeft, int theBottom)
            {
                HWIN_TRACE();
                left = theLeft;
                bottom = theBottom;
                return *this;
            }


            Point RightBottom() const
            {
                HWIN_TRACE();
                return Point(right,bottom);
            }

            Rectangle& SetRightBottom(const Point& pt)
            {
                HWIN_TRACE();
                right = pt.X();
                bottom = pt.Y();
                return *this;
            }

            Rectangle& SetRightBottom(int theRight, int theBottom)
            {
                HWIN_TRACE();
                right = theRight;
                bottom = theBottom;
                return *this;
            }

            Point Center() const
            {
                HWIN_TRACE();
                return Point((left+right)/2,(top+bottom)/2);
            }

            Rectangle& SetCenter(const Point& pt)
            {
                HWIN_TRACE();
                int width = (right-left);
                int height = (bottom - top);
                left = pt.X() - (width/2);
                top = pt.Y() - (height/2);
                right = left + width;
                bottom = top + height;
                return *this;
            }

            Point LeftCenter() const
            {
                HWIN_TRACE();
                return Point(left,(top+bottom)/2);
            }

            Point RightCenter() const
            {
                HWIN_TRACE();
                return Point(right,(top+bottom)/2);
            }

            Point TopCenter() const
            {
                HWIN_TRACE();
                return Point((left+right)/2,top);
            }

            Point BottomCenter() const
            {
                HWIN_TRACE();
                return Point((left+right)/2,bottom);
            }



            Size Size() const
            {
                HWIN_TRACE();
                return harlinn::windows::Size(labs(right - left),labs(bottom - top));
            }


            operator RECT& () 
            { 
                HWIN_TRACE();
                return *((RECT*)&left); 
            }
            operator const RECT& () const 
            { 
                HWIN_TRACE();
                return *((RECT*)&left); 
            }
        };
#pragma pack(pop)


        enum class DrawCaptionOptions : int
        {
            Active           = 0x0001,
            SmallCaption     = 0x0002,
            Icon             = 0x0004,
            Text             = 0x0008,
            InButton         = 0x0010,
            Gradient         = 0x0020,
            Buttons          = 0x1000
        };
        DEFINE_ENUM_FLAG_OPERATORS(DrawCaptionOptions)

        enum class ForegroundMixMode : int
        {
            Black            = 1,   /*  0       */
            NotMergePen      = 2,   /* DPon     */
            MaskNotPen       = 3,   /* DPna     */
            NotCopyPen       = 4,   /* PN       */
            MaskPenNot       = 5,   /* PDna     */
            Not              = 6,   /* Dn       */
            XorPen           = 7,   /* DPx      */
            NotMaskPen       = 8,   /* DPan     */
            MaskPen          = 9,   /* DPa      */
            NotXorPen        = 10,  /* DPxn     */
            Nop              = 11,  /* D        */
            MergeNotPen      = 12,  /* DPno     */
            CopyPen          = 13,  /* P        */
            MergePenNot      = 14,  /* PDno     */
            MergePen         = 15,  /* DPo      */
            White            = 16  /*  1       */
        };


        enum class BackgroundMixMode : int
        {
            Transparent         = 1,
            Opaque              = 2
        };

        enum class BorderStyle : UINT
        {
            RaisedOuter = 0x0001,
            SunkenOuter = 0x0002,
            RaisedInner = 0x0004,
            SunkenInner = 0x0008,
            Raised      = (BDR_RAISEDOUTER | BDR_RAISEDINNER),
            Sunken      = (BDR_SUNKENOUTER | BDR_SUNKENINNER),
            Etched      = (BDR_SUNKENOUTER | BDR_RAISEDINNER),
            Bump        = (BDR_RAISEDOUTER | BDR_SUNKENINNER)
        };
        DEFINE_ENUM_FLAG_OPERATORS(BorderStyle)

        enum class BorderFlags : UINT
        {
            Left         = 0x0001,
            Top          = 0x0002,
            Right        = 0x0004,
            Bottom       = 0x0008,

            TopLeft      = (BF_TOP | BF_LEFT),
            TopRight     = (BF_TOP | BF_RIGHT),
            BottomLeft   = (BF_BOTTOM | BF_LEFT),
            BottomRight  = (BF_BOTTOM | BF_RIGHT),
            Rectangle    = (BF_LEFT | BF_TOP | BF_RIGHT | BF_BOTTOM),

            Diagonal     = 0x0010,

            // For diagonal lines, the BF_RECT flags specify the end point of the
            // vector bounded by the rectangle parameter.
            DiagonalEndTopRight     = (BF_DIAGONAL | BF_TOP | BF_RIGHT),
            DiagonalEndTopLeft      = (BF_DIAGONAL | BF_TOP | BF_LEFT),
            DiagonalEndBottomLeft   = (BF_DIAGONAL | BF_BOTTOM | BF_LEFT),
            DiagonalEndBottomRight  = (BF_DIAGONAL | BF_BOTTOM | BF_RIGHT),


            Middle       = 0x0800,  /* Fill in the middle */
            Soft         = 0x1000,  /* For softer buttons */
            Adjust       = 0x2000,  /* Calculate the space left over */
            Flat         = 0x4000,  /* For flat rather than 3D borders */
            Mono         = 0x8000  /* For monochrome borders */
        };
        DEFINE_ENUM_FLAG_OPERATORS(BorderFlags)


        enum class DrawFrameControlType : UINT
        {
            Caption             = 1,
            MenuBar             = 2,
            ScrollBar           = 3,
            Button              = 4,
            PopupMenu           = 5
        };

        enum class DrawFrameControlCaptionPart
        {
            CloseButton       = 0x0000,
            MinimizeButton    = 0x0001,
            MaximizeButton    = 0x0002,
            RestoreButton     = 0x0003,
            HelpButton        = 0x0004
        };

        enum class DrawFrameControlMenuBarPart
        {
            Arrow          = 0x0000,
            Check          = 0x0001,
            Bullet         = 0x0002,
            ArrowRight     = 0x0004
        };


        enum class DrawFrameControlScrollBarPart
        {
            Up           = 0x0000,
            Down         = 0x0001,
            Left         = 0x0002,
            Right        = 0x0003,
            ComboBox     = 0x0005,
            SizeGrip     = 0x0008,
            SizeGripRight = 0x0010
        };

        enum class DrawFrameControlButtonOptions
        {
            CheckBox        = 0x0000,
            RadioImage      = 0x0001,
            RadioMask       = 0x0002,
            RadioButton     = 0x0004,
            ThreeState      = 0x0008,
            PushButton      = 0x0010
        };
        DEFINE_ENUM_FLAG_OPERATORS(DrawFrameControlButtonOptions)

        enum class DrawFrameControlPopupMenuPart
        {
            Arrow          = 0x0000,
            Check          = 0x0001,
            Bullet         = 0x0002,
            ArrowRight     = 0x0004
        };

        enum class DrawFrameControlOptions : UINT
        {
            None               = 0x0000,
            Inactive           = 0x0100,
            Pushed             = 0x0200,
            Checked            = 0x0400,
            Transparent        = 0x0800,
            HotTracked         = 0x1000,
            AdjustRectangle    = 0x2000,
            Flat               = 0x4000,
            Mono               = 0x8000
        };
        DEFINE_ENUM_FLAG_OPERATORS(DrawFrameControlOptions)

        enum class DrawStateFlags
        {
            Normal      = 0x0000,
            Prefix      = 0x0002,
            Dithered    = 0x0010,  /* Gray string appearance */
            Disabled    = 0x0020,
            Mono        = 0x0080,
            HidePrefix  = 0x0200,
            PrefixOnly  = 0x0400,
            Right       = 0x8000
        };
        DEFINE_ENUM_FLAG_OPERATORS(DrawStateFlags)


        enum class BoundsAccumulationFlags
        {
            Reset       = 0x0001,
            Accumulate  = 0x0002,
            Dirty       = DCB_ACCUMULATE,
            Set         = (DCB_RESET | DCB_ACCUMULATE),
            Enable      = 0x0004,
            Disable     = 0x0008
        };
        DEFINE_ENUM_FLAG_OPERATORS(BoundsAccumulationFlags)

        enum class ArcDirection
        {
            CounterClockwise = AD_COUNTERCLOCKWISE,
            Clockwise = AD_CLOCKWISE
        };

        enum class PolyDrawCommand : BYTE
        {
            CloseFigure = PT_CLOSEFIGURE,
            LineTo = PT_LINETO,
            LineToAndClose = PT_LINETO | PT_CLOSEFIGURE,
            BezierTo = PT_BEZIERTO,
            BezierToAndClose = PT_BEZIERTO | PT_CLOSEFIGURE,
            MoveTo = PT_MOVETO
        };
        DEFINE_ENUM_FLAG_OPERATORS(PolyDrawCommand)


        enum class DrawTextFlags : UINT
        {
            Top                      = 0x00000000,
            Left                     = 0x00000000,
            Center                   = 0x00000001,
            Right                    = 0x00000002,
            VCenter                  = 0x00000004,
            Bottom                   = 0x00000008,
            WordBreak                = 0x00000010,
            SingleLine               = 0x00000020,
            ExpandTabs               = 0x00000040,
            TabStop                  = 0x00000080,
            NoClip                   = 0x00000100,
            ExternalLeading          = 0x00000200,
            CalcRect                 = 0x00000400,
            NoPrefix                 = 0x00000800,
            Internal                 = 0x00001000,
            EditControl              = 0x00002000,
            PathEllipsis            = 0x00004000,
            EndEllipsis             = 0x00008000,
            ModifyString             = 0x00010000,
            RtlReading               = 0x00020000,
            WordEllipsis            = 0x00040000,
            NoFullWidthCharBreak     = 0x00080000,
            HidePrefix               = 0x00100000,
            PrefixOnly               = 0x00200000
        };
        DEFINE_ENUM_FLAG_OPERATORS(DrawTextFlags)

        enum class TextAlignment : UINT
        {
            NoUpdateCP                = 0,
            Left                      = 0,
            Top                       = 0,
            UpdateCP                  = 1,
            Right                     = 2,
            Center                    = 6,
            Bottom                    = 8,
            Baseline                  = 24,
            RtlReading                = 256
        };
        DEFINE_ENUM_FLAG_OPERATORS(TextAlignment)

        enum class GraphicsMode
        {
            Compatible = GM_COMPATIBLE,
            Advanced = GM_ADVANCED
        };


        enum class MapMode
        {
            Text             = 1,
            LoMetric         = 2,
            HiMetric         = 3,
            LoEnglish        = 4,
            HiEnglish        = 5,
            Twips            = 6,
            Isotropic        = 7,
            Anisotropic      = 8
        };


        enum class RasterOperation : DWORD
        {
            SourceCopy              = 0x00CC0020, /* dest = source                   */
            SourcePaint             = 0x00EE0086, /* dest = source OR dest           */
            SourceOrDestination     = 0x00EE0086, /* dest = source OR dest           */
            SourceAndDestination    = 0x008800C6, /* dest = source AND dest          */
            SourceInvert            = 0x00660046, /* dest = source XOR dest          */
            SourceXorDestination    = 0x00660046, /* dest = source XOR dest          */
            SourceErase             = 0x00440328, /* dest = source AND (NOT dest )   */
            SourceAndNotDestination   = 0x00440328, /* dest = source AND (NOT dest )   */
            NotSourceCopy           = 0x00330008, /* dest = (NOT source)             */
            NotSourceErase          = 0x001100A6, /* dest = (NOT src) AND (NOT dest) */
            NotSourceAndNotDestination = 0x001100A6, /* dest = (NOT src) AND (NOT dest) */
            MergeCopy               = 0x00C000CA, /* dest = (source AND pattern)     */
            MergePaint              = 0x00BB0226, /* dest = (NOT source) OR dest     */
            PatternCopy             = 0x00F00021, /* dest = pattern                  */
            PatternPaint            = 0x00FB0A09, /* dest = DPSnoo                   */
            PatternInvert           = 0x005A0049, /* dest = pattern XOR dest         */
            DestinationInvert       = 0x00550009, /* dest = (NOT dest)               */
            Blackness               = 0x00000042, /* dest = BLACK                    */
            Whiteness               = 0x00FF0062, /* dest = WHITE                    */
            NoMirrorBitmap          = 0x80000000, /* Do not Mirror the bitmap in this call */
            CaptureBlt              = 0x40000000 /* Include layered windows */
        };


        class DeviceContextHandle : public Handle
        {
            HPEN originalPen;
            HBRUSH originalBrush;
            HBITMAP originalBitmap;
            HFONT originalFont;
        protected: 
            HWIN_EXPORT DeviceContextHandle( );

            HWIN_EXPORT void SaveDefaultObjects();
            HWIN_EXPORT void RestoreDefaultObjects();

        public:
            typedef Handle Base;

            HWIN_EXPORT DeviceContextHandle(HDC theHandle, bool ownsHandle = true);

            HWIN_EXPORT ~DeviceContextHandle( );

            operator HDC() const
            {
                HWIN_TRACE();
                return static_cast<HDC>(Value());
            }

            HDC GetHDC() const
            {
                HWIN_TRACE();
                return static_cast<HDC>(Value());
            }

            HWIN_EXPORT std::shared_ptr<PenHandle> Pen() const;
            HWIN_EXPORT std::shared_ptr<PenHandle> SetPen(const std::shared_ptr<PenHandle>& newPen);

            HWIN_EXPORT std::shared_ptr<BrushHandle> Brush() const;
            HWIN_EXPORT std::shared_ptr<BrushHandle> SetBrush(const std::shared_ptr<BrushHandle>& newBrush);

            HWIN_EXPORT std::shared_ptr<BitmapHandle> Bitmap() const;
            HWIN_EXPORT std::shared_ptr<BitmapHandle> SetBitmap(const std::shared_ptr<BitmapHandle>& newBitmap);

            HWIN_EXPORT std::shared_ptr<FontHandle> Font() const;
            HWIN_EXPORT std::shared_ptr<FontHandle> SetFont(const std::shared_ptr<FontHandle>& newFont);


            HWIN_EXPORT DeviceContextHandle& DrawCaption(std::shared_ptr<Control> control, const RECT& boundingRectangle, DrawCaptionOptions options);

            HWIN_EXPORT DeviceContextHandle& DrawEdge(RECT& boundingRectangle, BorderStyle borderStyle, BorderFlags borderFlags );
            HWIN_EXPORT DeviceContextHandle& DrawFocusRect(RECT& boundingRectangle );

            HWIN_EXPORT DeviceContextHandle& DrawCaptionFrameControl(DrawFrameControlCaptionPart part, RECT& boundingRectangle, DrawFrameControlOptions options);
            HWIN_EXPORT DeviceContextHandle& DrawMenuBarFrameControl(DrawFrameControlMenuBarPart part, RECT& boundingRectangle, DrawFrameControlOptions options);
            HWIN_EXPORT DeviceContextHandle& DrawScrollBarFrameControl(DrawFrameControlScrollBarPart part, RECT& boundingRectangle, DrawFrameControlOptions options);
            HWIN_EXPORT DeviceContextHandle& DrawButtonFrameControl(DrawFrameControlButtonOptions buttonOptions, RECT& boundingRectangle, DrawFrameControlOptions options);
            HWIN_EXPORT DeviceContextHandle& DrawPopupMenuFrameControl(DrawFrameControlPopupMenuPart part, RECT& boundingRectangle, DrawFrameControlOptions options);


            HWIN_EXPORT DeviceContextHandle& DrawState(const String& theText, int x,int y,int cx,int cy,DrawStateFlags flags);
            HWIN_EXPORT DeviceContextHandle& DrawState(const String& theText, int x,int y,DrawStateFlags flags);

            HWIN_EXPORT DeviceContextHandle& DrawState(std::shared_ptr<BrushHandle> brush, const String& theText, int x,int y,int cx,int cy,DrawStateFlags flags);
            HWIN_EXPORT DeviceContextHandle& DrawState(std::shared_ptr<BrushHandle> brush, const String& theText, int x,int y,DrawStateFlags flags);

            HWIN_EXPORT DeviceContextHandle& DrawState(std::shared_ptr<BitmapHandle> bitmap, int x,int y,int cx,int cy,DrawStateFlags flags);
            HWIN_EXPORT DeviceContextHandle& DrawState(std::shared_ptr<BitmapHandle> bitmap, int x,int y,DrawStateFlags flags);
            HWIN_EXPORT DeviceContextHandle& DrawState(std::shared_ptr<IconHandle> icon, int x,int y,int cx,int cy,DrawStateFlags flags);
            HWIN_EXPORT DeviceContextHandle& DrawState(std::shared_ptr<IconHandle> icon, int x,int y,DrawStateFlags flags);


            HWIN_EXPORT RegionType ExcludeUpdateRgn(std::shared_ptr<Control> control);
            HWIN_EXPORT static void Flush();
            HWIN_EXPORT static DWORD BatchLimit();
            HWIN_EXPORT static DWORD SetBatchLimit(DWORD newBatchLimit);

            HWIN_EXPORT ColorRef BackgroundColor() const;
            HWIN_EXPORT ColorRef SetBackgroundColor(COLORREF color);

            HWIN_EXPORT harlinn::windows::BackgroundMixMode BackgroundMixMode() const;
            HWIN_EXPORT harlinn::windows::BackgroundMixMode SetBackgroundMixMode(harlinn::windows::BackgroundMixMode mixMode);

            HWIN_EXPORT BoundsAccumulationFlags BoundsRect(RECT& boundingRectangle) const;
            HWIN_EXPORT BoundsAccumulationFlags BoundsRect(RECT& boundingRectangle, bool clear);
            HWIN_EXPORT BoundsAccumulationFlags SetBoundsRect(const RECT& boundingRectangle, BoundsAccumulationFlags flags);

            HWIN_EXPORT harlinn::windows::ForegroundMixMode ForegroundMixMode() const;
            HWIN_EXPORT harlinn::windows::ForegroundMixMode SetForegroundMixMode(harlinn::windows::ForegroundMixMode mixMode);

            HWIN_EXPORT DeviceContextHandle& DrawGrayString(const String& theText,int X,int Y,int nWidth = 0,int nHeight = 0);
            HWIN_EXPORT DeviceContextHandle& DrawGrayString(std::shared_ptr<BrushHandle> brush,const String& theText,int X,int Y,int nWidth = 0,int nHeight = 0);

            HWIN_EXPORT DeviceContextHandle& DrawDesktopWallPaper();

            HWIN_EXPORT DeviceContextHandle& DrawChord(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect,int nXRadial1,int nYRadial1,int nXRadial2,int nYRadial2);
            HWIN_EXPORT DeviceContextHandle& DrawChord(const RECT& rectangle,const POINT& start,const POINT& end);

            HWIN_EXPORT DeviceContextHandle& DrawEllipse(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect);
            HWIN_EXPORT DeviceContextHandle& DrawEllipse(const RECT& rectangle);

            HWIN_EXPORT DeviceContextHandle& DrawFilledRectangle(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect, std::shared_ptr<BrushHandle> brush);
            HWIN_EXPORT DeviceContextHandle& DrawFilledRectangle(const RECT& rectangle, std::shared_ptr<BrushHandle> brush);

            HWIN_EXPORT DeviceContextHandle& DrawFrameRectangle(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect, std::shared_ptr<BrushHandle> brush);
            HWIN_EXPORT DeviceContextHandle& DrawFrameRectangle(const RECT& rectangle, std::shared_ptr<BrushHandle> brush);

            HWIN_EXPORT DeviceContextHandle& DrawInvertedRectangle(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect);
            HWIN_EXPORT DeviceContextHandle& DrawInvertedRectangle(const RECT& rectangle);

            HWIN_EXPORT DeviceContextHandle& DrawPie(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect,int nXRadial1,int nYRadial1,int nXRadial2,int nYRadial2);
            HWIN_EXPORT DeviceContextHandle& DrawPie(const RECT& rectangle,const POINT& start,const POINT& end);

            HWIN_EXPORT DeviceContextHandle& DrawPolygon(const POINT *lpPoints, int nCount);
            HWIN_EXPORT DeviceContextHandle& DrawPolygon(const std::vector<POINT>& points);
            HWIN_EXPORT DeviceContextHandle& DrawPolygon(std::shared_ptr<const std::vector<POINT> > polygon);

            HWIN_EXPORT DeviceContextHandle& DrawPolyPolygons(const std::vector< std::vector<POINT> >& polyPolygons);
            HWIN_EXPORT DeviceContextHandle& DrawPolyPolygon(const POINT *lpPoints,const INT *lpPolyCounts,int nCount);

            HWIN_EXPORT DeviceContextHandle& DrawRectangle(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect);
            HWIN_EXPORT DeviceContextHandle& DrawRectangle(const RECT& rectangle);

            HWIN_EXPORT DeviceContextHandle& DrawRoundedRectangle(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect,int nWidth,int nHeight);
            HWIN_EXPORT DeviceContextHandle& DrawRoundedRectangle(const RECT& rectangle,int nWidth,int nHeight);
            HWIN_EXPORT DeviceContextHandle& DrawRoundedRectangle(const RECT& rectangle,const SIZE& ellipseSize);

            HWIN_EXPORT DeviceContextHandle& DrawAngleArc(int X,int Y,DWORD dwRadius,FLOAT eStartAngle,FLOAT eSweepAngle);
            HWIN_EXPORT DeviceContextHandle& DrawAngleArc(const POINT& center,DWORD dwRadius,FLOAT eStartAngle,FLOAT eSweepAngle);

            HWIN_EXPORT DeviceContextHandle& DrawArc(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect,int nXStartArc,int nYStartArc,int nXEndArc,int nYEndArc);
            HWIN_EXPORT DeviceContextHandle& DrawArc(const RECT& rectangle,const POINT& start,const POINT& end);

            HWIN_EXPORT harlinn::windows::ArcDirection ArcDirection() const;
            HWIN_EXPORT harlinn::windows::ArcDirection SetArcDirection(harlinn::windows::ArcDirection newArcDirection);

            HWIN_EXPORT DeviceContextHandle& DrawLineTo(int nXEnd,int nYEnd);
            HWIN_EXPORT DeviceContextHandle& DrawLineTo(const POINT& endPoint);

            HWIN_EXPORT DeviceContextHandle& MoveTo(int newX,int newY);
            HWIN_EXPORT DeviceContextHandle& MoveTo(int newX,int newY, int& previousX, int& previousY );
            HWIN_EXPORT DeviceContextHandle& MoveTo(const POINT& newPosition);
            HWIN_EXPORT DeviceContextHandle& MoveTo(const POINT& newPosition, POINT& previousPosition);

            HWIN_EXPORT DeviceContextHandle& DrawPolyBezier(const POINT *lppt,DWORD cPoints);
            HWIN_EXPORT DeviceContextHandle& DrawPolyBezier(const std::vector<POINT>& points);
            HWIN_EXPORT DeviceContextHandle& DrawPolyBezier(std::shared_ptr<const std::vector<POINT> > points);

            HWIN_EXPORT DeviceContextHandle& DrawPolyBezierTo(const POINT *lppt,DWORD cPoints);
            HWIN_EXPORT DeviceContextHandle& DrawPolyBezierTo(const std::vector<POINT>& points);
            HWIN_EXPORT DeviceContextHandle& DrawPolyBezierTo(std::shared_ptr<const std::vector<POINT> > points);

            HWIN_EXPORT DeviceContextHandle& Draw(const POINT *lppt,const PolyDrawCommand *lpbTypes,int cCount);

            HWIN_EXPORT DeviceContextHandle& DrawPolyLine(const POINT *lppt,DWORD cPoints);
            HWIN_EXPORT DeviceContextHandle& DrawPolyLine(const std::vector<POINT>& points);
            HWIN_EXPORT DeviceContextHandle& DrawPolyLine(std::shared_ptr<const std::vector<POINT> > points);

            HWIN_EXPORT DeviceContextHandle& DrawPolyLineTo(const POINT *lppt,DWORD cPoints);
            HWIN_EXPORT DeviceContextHandle& DrawPolyLineTo(const std::vector<POINT>& points);
            HWIN_EXPORT DeviceContextHandle& DrawPolyLineTo(std::shared_ptr<const std::vector<POINT> > points);

            HWIN_EXPORT ColorRef TextColor() const;
            HWIN_EXPORT ColorRef SetTextColor(COLORREF colorRef);


            HWIN_EXPORT harlinn::windows::TextAlignment TextAlignment() const;
            HWIN_EXPORT harlinn::windows::TextAlignment SetTextAlignment(harlinn::windows::TextAlignment textAlignment);


            HWIN_EXPORT int DrawText(const String& theText,RECT& rect, DrawTextFlags uFormat);
            HWIN_EXPORT int DrawText(LPCTSTR lpchText,int nCount,RECT& rect, DrawTextFlags uFormat);
            HWIN_EXPORT int DrawText(LPWSTR lpchText,int nCount,RECT& rect, DrawTextFlags uFormat, DRAWTEXTPARAMS& drawTextParams);
            HWIN_EXPORT DeviceContextHandle& DrawText(int nXStart,int nYStart,LPCTSTR lpString,int cchString);
            HWIN_EXPORT DeviceContextHandle& DrawText(int nXStart,int nYStart,const String& theText);
            HWIN_EXPORT DeviceContextHandle& DrawText(const POINT& startPosition,const String& theText);
            HWIN_EXPORT SIZE DrawText(int X, int Y,LPCTSTR lpString, int nCount, int nTabPositions, const LPINT lpnTabStopPositions, int nTabOrigin);
            HWIN_EXPORT DeviceContextHandle& DrawText(int X,int Y, UINT fuOptions, const RECT *lprc, LPCTSTR lpString, UINT cbCount, const INT *lpDx);

            HWIN_EXPORT POINT CurrentPosition() const;
            HWIN_EXPORT const DeviceContextHandle& CurrentPosition(POINT& currentPosition) const;

            HWIN_EXPORT harlinn::windows::GraphicsMode GraphicsMode() const;
            HWIN_EXPORT harlinn::windows::GraphicsMode SetGraphicsMode(harlinn::windows::GraphicsMode newGraphicsMode);

            HWIN_EXPORT harlinn::windows::MapMode MapMode() const;
            HWIN_EXPORT harlinn::windows::MapMode SetMapMode(harlinn::windows::MapMode newMapMode);

            HWIN_EXPORT SIZE ViewportExtent() const;
            HWIN_EXPORT SIZE SetViewportExtent(const SIZE& newViewportExtent );
            HWIN_EXPORT SIZE ScaleViewportExtent(int Xnum,int Xdenom,int Ynum,int Ydenom);

            HWIN_EXPORT POINT ViewportOrigin() const;
            HWIN_EXPORT POINT SetViewportOrigin(const POINT& newViewportOrigin);
            HWIN_EXPORT POINT OffsetViewportOrigin(int xOffset, int yOffset);

            HWIN_EXPORT SIZE WindowExtent() const;
            HWIN_EXPORT SIZE SetWindowExtent(const SIZE& newWindowExtent );
            HWIN_EXPORT SIZE ScaleWindowExtent(int Xnum,int Xdenom,int Ynum,int Ydenom);

            HWIN_EXPORT POINT WindowOrigin() const;
            HWIN_EXPORT POINT SetWindowOrigin(const POINT& newWindowOrigin);
            HWIN_EXPORT POINT OffsetWindowOrigin(int xOffset, int yOffset);

            HWIN_EXPORT const DeviceContextHandle& WorldTransform(XFORM& xform) const;
            HWIN_EXPORT XFORM WorldTransform( ) const;

            HWIN_EXPORT DeviceContextHandle& SetWorldTransform(XFORM& xform);

            HWIN_EXPORT DeviceContextHandle& ModifyWorldTransform(const XFORM& xform, bool rightMultiply = false);
            HWIN_EXPORT DeviceContextHandle& ResetWorldTransform( );


            HWIN_EXPORT DeviceContextHandle& DrawBitmap(std::shared_ptr<BitmapHandle> bitmap);
            HWIN_EXPORT DeviceContextHandle& DrawBitmap(std::shared_ptr<BitmapHandle> bitmap, const POINT& position);
            HWIN_EXPORT DeviceContextHandle& DrawBitmap(std::shared_ptr<BitmapHandle> bitmap, const POINT& position, const SIZE size);

            HWIN_EXPORT DeviceContextHandle& DrawBitmap(std::shared_ptr<DeviceContextHandle> source);
            HWIN_EXPORT DeviceContextHandle& DrawBitmap(std::shared_ptr<DeviceContextHandle> source, const POINT& position);
            HWIN_EXPORT DeviceContextHandle& DrawBitmap(std::shared_ptr<DeviceContextHandle> source, const POINT& position, const SIZE size);



        };


        enum class WindowDeviceContextFlags : int
        {
            // Returns a DeviceContext that corresponds to the window 
            // rectangle rather than the client rectangle.
            Window           = 0x00000001L,
            // Returns a DeviceContext  from the cache, rather than the OWNDC or 
            // CLASSDC window. Essentially overrides CS_OWNDC and CS_CLASSDC
            Cache            = 0x00000002L,
            // Does not reset the attributes of this DeviceContext  to the 
            // default attributes when this DC is released.
            NoResetAttributes = 0x00000004L,
            // Excludes the visible regions of all child windows 
            // below the window identified by hWnd.
            ClipChildren     = 0x00000008L,
            // Excludes the visible regions of all sibling windows above 
            // the window identified by hWnd
            ClipSiblings     = 0x00000010L,
            // Uses the visible region of the parent window. The parent's 
            // WS_CLIPCHILDREN and CS_PARENTDC style bits are ignored. The origin is 
            // set to the upper-left corner of the window identified by hWnd.
            ParentClip       = 0x00000020L,
            // The clipping region identified by hrgnClip is excluded from 
            // the visible region of the returned DeviceContext.
            ExcludeRegion    = 0x00000040L,
            // The clipping region identified by hrgnClip is intersected with the 
            // visible region of the returned DeviceContext
            IntersectRegion  = 0x00000080L,

            ExcludeUpdate    = 0x00000100L,
            //IntersectUpdate  = 0x00000200L,

            // Allows drawing even if there is a LockWindowUpdate call in effect that would 
            // otherwise exclude this window. Used for drawing during tracking.
            LockWindowUpdate = 0x00000400L,
            //Validate         = 0x00200000L
        };

        class WindowDeviceContextHandle : public DeviceContextHandle
        {
            
        public:
            typedef DeviceContextHandle Base;
        };


        class PaintDeviceContextHandle : public DeviceContextHandle
        {
            PAINTSTRUCT paintStruct;
            HWND windowHandle;
        public:
            typedef DeviceContextHandle Base;

            HWIN_EXPORT PaintDeviceContextHandle(const std::shared_ptr<Control> theControl);
            HWIN_EXPORT PaintDeviceContextHandle(HWND hWnd);

            HWIN_EXPORT virtual ~PaintDeviceContextHandle();
        };


        class MemoryDeviceContextHandle : public DeviceContextHandle
        {
        public:
            typedef DeviceContextHandle Base;

            HWIN_EXPORT MemoryDeviceContextHandle(std::shared_ptr<DeviceContextHandle> deviceContext);
            HWIN_EXPORT MemoryDeviceContextHandle(std::shared_ptr<DeviceContextHandle> deviceContext, std::shared_ptr<BitmapHandle> theBitmap);
            HWIN_EXPORT virtual ~MemoryDeviceContextHandle();

        };




        /*
        class Accelerator : public Handle
        {
        public:
            typedef Handle Base;

        };*/


        class BitmapSelection
        {
            std::shared_ptr<DeviceContextHandle> deviceContext;
            std::shared_ptr<BitmapHandle> previouslySelectedBitmap;
        public:
            BitmapSelection(std::shared_ptr<DeviceContextHandle> theDeviceContext, std::shared_ptr<BitmapHandle> theBitmap)
                : deviceContext(theDeviceContext)
            {
                HWIN_TRACE();
                previouslySelectedBitmap = deviceContext->SetBitmap(theBitmap);
            }
            ~BitmapSelection()
            {
                HWIN_TRACE();
                deviceContext->SetBitmap(previouslySelectedBitmap);
            }
        };


        class BrushSelection
        {
            std::shared_ptr<DeviceContextHandle> deviceContext;
            std::shared_ptr<BrushHandle> previouslySelectedBrush;
        public:
            BrushSelection(std::shared_ptr<DeviceContextHandle> theDeviceContext, std::shared_ptr<BrushHandle> theBrush)
                : deviceContext(theDeviceContext)
            {
                HWIN_TRACE();
                previouslySelectedBrush = deviceContext->SetBrush(theBrush);
            }
            ~BrushSelection()
            {
                HWIN_TRACE();
                deviceContext->SetBrush(previouslySelectedBrush);
            }
        };


        class PenSelection
        {
            std::shared_ptr<DeviceContextHandle> deviceContext;
            std::shared_ptr<PenHandle> previouslySelectedPen;
        public:
            PenSelection(std::shared_ptr<DeviceContextHandle> theDeviceContext, std::shared_ptr<PenHandle> thePen)
                : deviceContext(theDeviceContext)
            {
                HWIN_TRACE();
                previouslySelectedPen = deviceContext->SetPen(thePen);
            }
            ~PenSelection()
            {
                HWIN_TRACE();
                deviceContext->SetPen(previouslySelectedPen);
            }
        };

        class FontSelection
        {
            std::shared_ptr<DeviceContextHandle> deviceContext;
            std::shared_ptr<FontHandle> previouslySelectedFont;
        public:
            FontSelection(std::shared_ptr<DeviceContextHandle> theDeviceContext, std::shared_ptr<FontHandle> theFont)
                : deviceContext(theDeviceContext)
            {
                HWIN_TRACE();
                previouslySelectedFont = deviceContext->SetFont(theFont);
            }
            ~FontSelection()
            {
                HWIN_TRACE();
                deviceContext->SetFont(previouslySelectedFont);
            }
        };


    };
};

#endif 